/**************************************************************************
* DS_DELEGATE.CPP                                              02.06.2007 *
*                                                                         *
* .                                                                       *
**************************************************************************/

#include "ap\ap_comm.h"
#include "ds\ds_delegate.h"

namespace ds {

/**************************************************************************
* DELEGATE_THREAD::ThreadProc()                                           *
*                                                                         *
**************************************************************************/
void DELEGATE_THREAD::ThreadProc(void * param)
{
   const int THREAD_PROCESSOR = 2;
   osSetCurThreadProcessor(THREAD_PROCESSOR);

   DELEGATE_THREAD * thread = (DELEGATE_THREAD *)param;

   // initialization
   thread->threadId  = osGetCurThreadId();
   thread->working   = true;

   osSetSignal(thread->initialized);

   for (;;) {
      osWaitForSignal(thread->queueNotEmpty);

      if (!thread->working) {
         break;
      }

      thread->queueLock.Lock();
      if (thread->queue.IsEmpty()) {
         osResetSignal(thread->queueNotEmpty);
         osSetSignal(thread->queueEmpty);
         thread->queueLock.Unlock();
         continue;
      }

      ds::DELEGATE * del = thread->queue.Front();
      thread->queue.Erase(0);
      thread->queueLock.Unlock();

      del->Exec();
      delete del;
   }
}

/**************************************************************************
* DELEGATE_THREAD::Init()                                                 *
*                                                                         *
**************************************************************************/
void DELEGATE_THREAD::Init(void)
{
   STRONG_ASSERT(initialized == NULL);

   // initialize fmod's thread
   initialized    = osCreateSignal(TRUE, FALSE);
   queueEmpty     = osCreateSignal(TRUE, FALSE);
   queueNotEmpty  = osCreateSignal(TRUE, FALSE);
   thread         = osCreateThread(ThreadProc, this, "Delegate thread");

   osWaitForSignal(initialized);

   // check postcondition
   STRONG_ASSERT(working);
   STRONG_ASSERT(threadId != -1);
}

/**************************************************************************
* DELEGATE_THREAD::Term()                                                 *
*                                                                         *
**************************************************************************/
void DELEGATE_THREAD::Term(void)
{
   osWaitForSignal(queueEmpty);

   queueLock.Lock();
   STRONG_ASSERT(queue.IsEmpty());
   working = false;
   osSetSignal(queueNotEmpty);
   queueLock.Unlock();

   osDestroySignal(initialized);
   osDestroySignal(queueEmpty);
   osDestroySignal(queueNotEmpty);

   initialized = queueEmpty = queueNotEmpty = NULL;
}

} // namespace ds

//
// End-of-file DS_DELEGATE.CPP
//
